package peace.util.collection
{
	import peace.util.Arrays;
	
	
	
/** 
 * Коллекция объектов с индексированием по одному 
 * или нескольким уникальным строковым свойствам
 * 
 * Работает только с уникальными индексами - два 
 * объекта с одинаковым значением свойства в массив собирать
 * не станет
 */
public class Hash
{
	/**
	 * 
	 */	
	public var items:Array = [];
	/**
	 * 
	 */	
	protected var indexes:Object = {};
	/**
	 * 
	 * @param index String или Array of String
	 * @param items объект или массив объектов
	 * 
	 */	
	public function Hash (index:* = null, items:* = null)
	{
		addIndex(index);
		add(items);
	}
	/**
	 * Добавляем поля индексирования
	 * @param index String или Array of String
	 * 
	 */	
	public function addIndex (index:*):void
	{
		var arr:Array = index is Array ? index : [index]
		for each (var s:String in arr)
		{
			if (! indexes[s])
			{
				var o:Object = {};
				indexes[s] = o;
				// индексируем имеющееся говно
				for each (var ii:Object in items)
				{
					o [ii[s]] = ii;
				}
			}
		}
	}
	/**
	 * Добавляем объекты, индексируемые по заданным полям
	 * @param items объект или массив объектов
	 * 
	 */	
	public function add (items:*):void
	{
		if (!items) return;
		
		var arr:Array = items is Array ? items : [items]
		
		for each (var oo:Object in arr)
		{
			// добавляем в массив объектов коллекции
			this.items.push(oo);
			// индексируем по всем индексам
			for (var index:String in indexes)
			{
				indexes[index] [oo[index]] = oo;
			}
		}
		
	}
	/**
	 * Удаляем объекты
	 * @param items объект или массив объектов
	 * 
	 */	
	public function remove (items:*):void
	{
		var arr:Array = items is Array ? items : [items]
		var index:String;
		for each (var oo:Object in arr)
		{
			if ( Arrays.removeItem(oo,this.items) )
			{
				for (index in indexes)
				{
					delete indexes[index] [oo[index]];
				}
				
			}
		}
	}
	/**
	 * Удаляем все элементы 
	 */	
	public function removeAll ():void
	{
		items.length = 0;
		
		var index:String;
		for (index in indexes)
		{
			indexes[index] = {};
		}
	}
	/**
	 * Получаем объект по значению одного из уникальных ключей
	 * 
	 * @param propertyName имя индексного свойства
	 * @param value значение индексного свойства (string,int,uint)
	 * @return 
	 * 
	 */	
	public function getItem (propertyName:String, value:*):Object
	{
		return indexes[propertyName] ? indexes[propertyName][value] : null;
	}
	/**
	 * Для неуникальных свойств объектов - тупо выборка по циклу
	 *  
	 * @param propertyName
	 * @param value
	 * @return 
	 * 
	 */	
	public function getItemsBy (propertyName:String, value:*):Array
	{
		var ret:Array = [];
		
		for each (var o:Object in items)
		{
			if (o[propertyName] == value)
			{
				ret.push(o);
			}
		}
		
		return ret;
	}
	/**
	 * 
	 * @return 
	 * 
	 */	
	public function toString():String
	{
		return items.toString();
	}
	
	

}
}